package com.github.tomakehurst.wiremock.db.utils;

import com.github.tomakehurst.wiremock.common.Json;
import com.github.tomakehurst.wiremock.common.JsonException;
import com.github.tomakehurst.wiremock.db.entity.MultiMappingEntity;
import com.github.tomakehurst.wiremock.stubbing.StubMapping;
import com.github.tomakehurst.wiremock.stubbing.StubMappingCollection;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 专门处理 MultiMappingEntity 与业务模型（StubMappingCollection/StubMapping）的转换
 * 职责：封装 JSON 序列化/反序列化、字段映射逻辑，解耦 Service 与转换细节
 */
public class MultiMappingConverter {

    /**
     * 业务模型（StubMapping列表） -> MultiMappingEntity（数据库实体）
     * 用于「新增多Stub集合」场景，自动生成ID和创建时间
     */
    public MultiMappingEntity toEntity(String fileName, List<StubMapping> mappings) {
        // 1. 参数校验（提前拦截无效输入）
        if (fileName == null || fileName.trim().isEmpty()) {
            throw new IllegalArgumentException("多Stub集合文件名（fileName）不能为空");
        }
        if (mappings == null || mappings.isEmpty()) {
            throw new IllegalArgumentException("多Stub集合（mappings）不能为空，至少包含一个Stub");
        }

        // 2. 封装 StubMappingCollection 并序列化（仅包含核心字段）
        StubMappingCollection collection = new StubMappingCollection(mappings);
        String content;
        try {
            // 使用 writePrivate 避免序列化父类冗余字段（如StubMapping的dirty标记）
            content = Json.writePrivate(collection);
        } catch (JsonException e) {
            throw new RuntimeException("序列化多Stub集合失败：fileName=" + fileName, e);
        }

        // 3. 构建 Entity 并赋值（自动生成UUID和创建时间）
        MultiMappingEntity entity = new MultiMappingEntity();
        entity.setId(UUID.randomUUID().toString()); // 自动生成唯一ID
        entity.setFileName(fileName);
        entity.setContent(content);
        entity.setCreatedAt(LocalDateTime.now()); // 自动填充创建时间

        return entity;
    }

    /**
     * MultiMappingEntity -> 业务模型（StubMappingCollection）
     * 用于「解析单条多Stub集合」场景，保留完整集合结构
     */
    public StubMappingCollection toCollection(MultiMappingEntity entity) {
        if (entity == null) {
            throw new IllegalArgumentException("MultiMappingEntity 不能为null");
        }
        if (entity.getContent() == null || entity.getContent().trim().isEmpty()) {
            throw new RuntimeException("多Stub集合内容（content）为空：fileName=" + entity.getFileName());
        }

        try {
            return Json.read(entity.getContent(), StubMappingCollection.class);
        } catch (JsonException e) {
            throw new RuntimeException("反序列化多Stub集合失败：fileName=" + entity.getFileName() + "，content=" + entity.getContent(), e);
        }
    }

    /**
     * 批量转换：MultiMappingEntity列表 -> StubMapping列表
     * 用于「查询所有多Stub集合下的所有Stub」场景，扁平化集合结构
     */
    public List<StubMapping> batchToStubMappings(List<MultiMappingEntity> entities) {
        if (entities == null || entities.isEmpty()) {
            return List.of(); // 返回空列表，避免NPE
        }

        return entities.stream()
                .flatMap(entity -> {
                    try {
                        // 先转换为集合，再提取所有StubMapping
                        StubMappingCollection collection = toCollection(entity);
                        return collection.getMappingOrMappings().stream();
                    } catch (Exception e) {
                        // 捕获单条Entity解析异常，避免批量处理中断
                        throw new RuntimeException("解析多Stub集合失败：fileName=" + entity.getFileName() + "，id=" + entity.getId(), e);
                    }
                })
                .collect(Collectors.toList());
    }

    /**
     * 反向转换：StubMappingCollection -> MultiMappingEntity
     * 用于「更新多Stub集合」场景（若后续新增更新功能）
     */
    public MultiMappingEntity updateEntity(MultiMappingEntity oldEntity, StubMappingCollection newCollection) {
        if (oldEntity == null) {
            throw new IllegalArgumentException("待更新的MultiMappingEntity不能为null");
        }
        if (newCollection == null) {
            throw new IllegalArgumentException("新的StubMappingCollection不能为null");
        }

        try {
            // 仅更新content字段，保留原有id、fileName、createdAt（创建时间不修改）
            oldEntity.setContent(Json.writePrivate(newCollection));
            return oldEntity;
        } catch (JsonException e) {
            throw new RuntimeException("更新多Stub集合序列化失败：id=" + oldEntity.getId(), e);
        }
    }
}